/*
 * Copyright (C) 2014 Steven Kurilovitch
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.goodjaerb.swccg.ui;

import com.goodjaerb.swccg.core.CardData;
import com.goodjaerb.swccg.core.CardData.Field;
import com.goodjaerb.swccg.core.DeckListItem;
import com.goodjaerb.swccg.core.dnd.TransferableDeckListItem;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragSource;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;

/**
 *
 * @author Steven Kurilovitch
 */
public class CardPanel extends JPanel {
    private CardData card;
    private Image icon;
    private boolean mouseInside;
    private int iconWidth;
    private int iconHeight;
    
    private double widthScale;
    private double heightScale;
    private AffineTransform at;
    
    private IconPanel iconPanel;
    
    /**
     * Creates new form CardPanel
     */
    public CardPanel() {
        super();
        initComponents();
        titleLabel.setText("");
        titleLabel.setPreferredSize(new Dimension(200, 14));
        
        iconPanel = new IconPanel();
        add(iconPanel, BorderLayout.CENTER);
        iconPanel.setPreferredSize(new Dimension(200, 280));
        
        at = new AffineTransform();
    }
    
    public CardPanel(String imagePath) throws IOException {
        this();
        setImage(imagePath);
    }
    
    public Point getImageLocation() {
        Point p = getLocation();
        p.y += titleLabel.getHeight();
        return p;
    }
    
    public CardData getCard() {
        return card;
    }
    
    public void setCard(CardData card) throws IOException {
        this.setCard(card, false);
    }
    
    public void setCard(CardData card, boolean backSide) throws IOException {
        this.card = card;
        iconPanel.setCard(card);
        titleLabel.setFont(titleLabel.getFont().deriveFont(11f));
        if(card == null) {
            titleLabel.setText("");
            setImage(null);
        }
        else {
            String titleString = card.get(CardData.Field.TITLE) + " (" + card.get(CardData.Field.RARITY) + ")";
            int w = titleLabel.getGraphics().getFontMetrics().stringWidth(titleString);
            while(w > 200) {
                titleLabel.setFont(titleLabel.getFont().deriveFont(titleLabel.getFont().getSize2D() - 0.25f));
                w = titleLabel.getGraphics().getFontMetrics().stringWidth(titleString);
            }
            titleLabel.setText(titleString);
            if(backSide) {
                setImage(card.getBackImagePath());
            }
            else {
                setImage(card.getImagePath());
            }
        }
    }
    
    private void setImage(String imagePath) throws IOException {
        if(imagePath == null) {
            icon = null;
        }
        else {
            BufferedImage tmp = ImageIO.read(new File(imagePath));
            icon = tmp.getSubimage(6, 6, tmp.getWidth(null) - 10, tmp.getHeight(null) - 10);
            iconWidth = icon.getWidth(null);
            iconHeight = icon.getHeight(null);
            
            Graphics2D g = (Graphics2D)icon.getGraphics();
            g.setColor(card.get(Field.SET).contains("Introductory Two Player Game") ? Color.white : Color.black);
            g.fillRect(0, iconHeight - 12, 1000, 13);
            g.setColor(card.get(Field.SET).contains("Introductory Two Player Game") ? Color.black : Color.white);
            g.setFont(g.getFont().deriveFont(Font.PLAIN, 11f));
            g.drawString(card.get(Field.SET), 10, iconHeight - 3);
            g.dispose();
            
            rescale();
        }
    }
    
    public void rescale() {            
        setSize(200, 280 + titleLabel.getHeight());
        iconPanel.setSize(200, 280);
        at.setToIdentity();
        if(iconWidth > iconHeight) {
            widthScale = ((double)iconPanel.getWidth()) / iconHeight;
            heightScale = ((double)iconPanel.getHeight()) / iconWidth;
            at.scale(widthScale, heightScale);
            at.quadrantRotate(1, iconHeight / 2, iconHeight / 2);
        }
        else {
            widthScale = ((double)iconPanel.getWidth()) / iconWidth;
            heightScale = ((double)iconPanel.getHeight()) / iconHeight;
            at.scale(widthScale, heightScale);
        }
    }
    
    public double getWidthScale() {
        return widthScale;
    }
    
    public double getHeightScale() {
        return heightScale;
    }
    
    public Image getImage() {
        return icon;
    }
    
    public IconPanel getIconPanel() {
        return iconPanel;
    }
    
    public void setMouseInside(boolean b) {
        mouseInside = b;
    }
    
    public class IconPanel extends JPanel {        
        private CardData card;
        
        public IconPanel() {
            DragSource ds = new DragSource();
            ds.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY, (DragGestureEvent dge) -> {
                dge.startDrag(DragSource.DefaultCopyDrop, icon.getScaledInstance((int)(iconWidth * widthScale), (int)(iconHeight * heightScale), Image.SCALE_DEFAULT), dge.getDragOrigin(), new TransferableDeckListItem(new DeckListItem(card)), null);
            });
            
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseEntered(MouseEvent e) {
                    mouseInside = true;
                    repaint();
                }

                @Override
                public void mouseExited(MouseEvent e) {
                    mouseInside = false;
                    repaint();
                }
            });
        }
        
        public CardData getCard() {
            return card;
        }
        
        public void setCard(CardData card) {
            this.card = card;
        }
        
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            if(icon != null) {
                Graphics2D g2d = (Graphics2D)g.create();
                g2d.setClip(new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(), 14, 14));

                g2d.drawImage(icon, at, null);
                if(mouseInside) {
                    g2d.setColor(Color.blue);
                    g2d.setStroke(new BasicStroke(14f));
                    g2d.draw(new Rectangle2D.Double(0., 0., getWidth(), getHeight()));
                }
                g2d.dispose();
            }
        }
    }
    
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        titleLabel = new javax.swing.JLabel();

        setPreferredSize(new java.awt.Dimension(200, 294));
        setLayout(new java.awt.BorderLayout());

        titleLabel.setText("-");
        add(titleLabel, java.awt.BorderLayout.NORTH);
    }// </editor-fold>//GEN-END:initComponents


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel titleLabel;
    // End of variables declaration//GEN-END:variables
}
